import os, sys, logging
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

from google.appengine.dist import use_library
use_library('django', '1.1')

import settings
import utils
import datetime
from datetime import date, timedelta
import holidays
import tickets
from django.utils import simplejson

class Milestone(object):

    def __init__(self, gevent, project_id, holiday_calendar_id=False, appengine=False, start_date=None):
        self.title = gevent.title.text
        self.date, e = utils.parse_when(gevent.content)
        self.start_date = start_date
        self._cache = {}
        self.holiday_calendar_id = holiday_calendar_id
        self.appengine = appengine
        self.project_id = project_id
    
    def __str__(self):
        return "%s, %s:%s" % (self.title, self.start_date, self.date)
    
    def workdays_left(self):
        """Weekdays before milestone, not including holidays
        """
        return len(self.date_sequence())
    
    def work_left_hours(self):
        hours = 0
        for ticket in self.tickets():
            if self.not_closed(ticket):
                hours = hours + ticket.hours
        return hours
    
    def not_closed(self, ticket):
        if ticket.status == 'Fixed' or ticket.status == 'Closed' or ticket.status == 'Invalid' or ticket.status == 'WontFix' or ticket.status == 'Done' or ticket.status == 'Duplicate':
            return False
        return True
        
    def work_left_days(self):
        return float(self.work_left_hours()) / 8.0
    
    def hours_left_by_user(self):
        hours = {}
        for ticket in self.tickets():
            if not ticket.owner in hours.keys():
                hours[ticket.owner] = 0
            if self.not_closed(ticket):
                hours[ticket.owner] = hours[ticket.owner] + ticket.hours
        return hours
    
    def days_left_by_user(self):
        hours = self.hours_left_by_user()
        for key in hours:
            hours[key] = float(hours[key]) / 8.0
        return hours
    
    def uid(self):
        return self.title.replace('-', '').replace('.', '')
    
    def date_sequence(self):
        if 'date_sequence' not in self._cache.keys():
            hs = self.holidays()
            days = []
            day = self.start_date
            while day <= self.date:
                wday = day.isoweekday()
                if wday != 6 and wday != 7:
                    in_holiday = False
                    for holiday in hs:
                        if holiday.includes(day):
                            in_holiday = True
                    if not in_holiday:
                        days.append(day)
                day = day + timedelta(days=1)
            self._cache['date_sequence'] = days
        return self._cache['date_sequence']
    
    def holidays(self):
        if 'holidays' not in self._cache.keys():
            if self.holiday_calendar_id:
                self._cache['holidays'] = holidays.get(self.holiday_calendar_id, start_date=self.start_date, end_date=self.date, appengine=self.appengine)
            else:
                self._cache['holidays'] = []
        return self._cache['holidays']
    
    def current(self):
        """Whether today's date falls within this milestone.
        """
        return date.today() >= self.start_date and date.today() <= self.date
    
    def tickets(self):
        if 'tickets' not in self._cache.keys():
            self._cache['tickets'] = tickets.get(self.project_id, milestone=self.title, appengine=self.appengine)
        return self._cache['tickets']
    
    def tickets_json(self):
        out = []
        for ticket in self.tickets():
            if self.not_closed(ticket):
                out.append(ticket.to_json_object())
        return simplejson.dumps(out).replace("'", "\\'")
    
    def slug(self):
        return self.title.replace('.', '-')
        
def _date_cmp(x, y):
    if x.date > y.date:
        return 1
    elif x.date == y.date:
        return 0
    else:
        return -1

def get(calendar_id, project_id, start_date=None, end_date=None, appengine=False, holiday_calendar_id=False):
    """Retrieves all calendar events from the calendar feed identified in the
    MILESTONES setting. Returns events as a list of Milestone objects.
    """
    import gdata.calendar.service
    if start_date is None:
        start_date = str(date.today() - timedelta(weeks=4))
    if end_date is None:
        end_date = str(date.today() + timedelta(weeks=52))
    
    calendar_service = gdata.calendar.service.CalendarService()
    if appengine:
        import gdata.alt.appengine
        gdata.alt.appengine.run_on_appengine(calendar_service)
    # feed = calendar_service.GetCalendarEventFeed(uri=settings.HOLIDAY_FEED)
    query = gdata.calendar.service.CalendarEventQuery(calendar_id, "public", "basic") # , 'private', 'full'
    query.start_min = start_date
    query.start_max = end_date
    events = []
    for entry in calendar_service.CalendarQuery(query).entry:
        events.append(Milestone(entry, project_id, holiday_calendar_id=holiday_calendar_id, appengine=appengine))
    events.sort(_date_cmp)
    for i, m in enumerate(events):
        if i == 0:
            if m.date <= date.today():
                m.start_date = m.date + timedelta(days=1)
            else:
                m.start_date = date.today()
        else:
            m.start_date = events[i-1].date + timedelta(days=1)
            if m.start_date < date.today():
                m.start_date = date.today()
    return events